"""
@Author    : ghenyar
@Time      : 2025/8/28 12:54
@File      : handlers.py
@Desc      : 
"""
import traceback
from typing import Union, Callable, Awaitable
from fastapi import Request, status, HTTPException
from fastapi.responses import JSONResponse, Response
from fastapi.exceptions import RequestValidationError

from sqlalchemy.exc import SQLAlchemyError
from starlette.websockets import WebSocket

from app.common.exception.exceptions import BasesException
from app.common.response import ApiResponse

ExceptionHandler = Callable[[Request, Exception], Union[Response, Awaitable[Response]]]
WebSocketExceptionHandler = Callable[[WebSocket, Exception], Awaitable[None]]


async def base_exception_handler(request: Request, exc: BasesException) -> Response:
    """处理自定义基础异常"""
    return JSONResponse(
        status_code=exc.code,
        content=ApiResponse.exception_response(code=exc.code, status=-1, message=exc.message, data=exc.data)
    )


async def http_exception_handler(request: Request, exc: HTTPException) -> Response:
    """处理 HTTP 异常"""
    return JSONResponse(
        status_code=exc.status_code,
        content=ApiResponse.exception_response(
            code=exc.status_code,
            status=-1,
            message=exc.detail if isinstance(exc.detail, str) else "请求失败",
            data={"detail": str(exc.detail)} if not isinstance(exc.detail, str) else None
        )
    )


async def validation_exception_handler(request: Request, exc: RequestValidationError) -> Response:
    """处理请求参数验证异常"""
    errors = []
    for error in exc.errors():
        errors.append({
            "loc": error.get("loc", []),
            "msg": error.get("msg", ""),
            "type": error.get("type", "")
        })
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=ApiResponse.exception_response(
            code=422,
            status=-1,
            message="参数验证失败",
            data={"errors": errors}
        )
    )


async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError) -> Response:
    """处理数据库异常"""
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content=ApiResponse.exception_response(
            code=500,
            status=-1,
            message="数据库操作失败",
            data={"detail": str(exc)}
        )
    )


async def general_exception_handler(request: Request, exc: Exception) -> Response:
    """处理其他未知异常"""
    # 记录异常堆栈信息
    error_detail = traceback.format_exc()

    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content=ApiResponse.exception_response(
            code=500,
            status=-1,
            message="服务器内部错误",
            data={"detail": str(exc)} if request.app.debug else None
        )
    )
